# coding : utf-8

# http://m.biancheng.net/pandas/what-is-pandas.html
# https://matplotlib.org/stable/api/matplotlib_configuration_api.html
# https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.scatter.html
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
import re

class TA:
    def __init__(self, kwargs):
        self.set_acc = set()
        self.df = pd.DataFrame()
        plt = None
        self.kwargs=kwargs
        
    def get_acc_no_before(self, col_num=3):
        '''从交易文件中读取所有账号'''
        df = pd.read_table(self.kwargs['FILE']['filepath'],
                            sep=self.kwargs['FILE']['separator'], 
                            header=self.kwargs['FILE']['header'],
                            usecols=[col_num],
                            names=['acc_no'],
                            dtype={'acc_no':str},
                            encoding=self.kwargs['FILE']['encoding'],
                            error_bad_lines=False
                            )
                            
        for i in df['acc_no']:
            self.set_acc.add(i)
        print("账号数量合计：", len(self.set_acc))
        
    def get_data_chunk_columns(self, names, dtype, usecols, acc_no=None):
        """分区块读取交易数据文件，txt"""
        chunk_list = []
        df = pd.DataFrame()
        data_iterator = pd.read_table(self.kwargs['FILE']['filepath'],
                            sep=self.kwargs['FILE']['separator'], 
                            header=self.kwargs['FILE']['header'],
                            encoding=self.kwargs['FILE']['encoding'],
                            names=names,
                            dtype=dtype,
                            usecols=usecols,
                            chunksize=self.kwargs['FILE']['chunksize'],
                            error_bad_lines=False
                            )
        for data_chunk in data_iterator:
            df = df.append(data_chunk[data_chunk['Acc_no']==acc_no])
            #print(df)
        self.df = df
        
    def get_data_chunk(self, names, dtype, acc_no=None):
        """分区块读取交易数据文件，txt"""
        chunk_list = []
        df = pd.DataFrame()
        data_iterator = pd.read_table(self.kwargs['FILE']['filepath'],
                            sep=self.kwargs['FILE']['separator'], 
                            header=self.kwargs['FILE']['header'],
                            encoding=self.kwargs['FILE']['encoding'],
                            names=names,
                            dtype=dtype,
                            chunksize=self.kwargs['FILE']['chunksize'],
                            error_bad_lines=False
                            )
        for data_chunk in data_iterator:
            #print(df)
            df = df.append(data_chunk[data_chunk['Acc_no']==acc_no])
        self.df = df
        
    def get_data(self, names, dtype):
        """读取交易数据文件，txt"""
        self.df = pd.read_table(self.kwargs['FILE']['filepath'],
                    sep=self.kwargs['FILE']['separator'],
                    header=self.kwargs['FILE']['header'],
                    encoding=self.kwargs['FILE']['encoding'],
                    names=names,
                    dtype=dtype,
                    error_bad_lines=False
                    )
        # 打印数据的前5行
        #print(self.df.head())
        #print(self.df.dtypes)
        
    def get_acc_no(self):
        '''从交易文件中读取所有账号'''
        for i in self.df['Acc_no']:
            self.set_acc.add(i)
        print("账号数量合计：", len(self.set_acc))
        
    def flush_data(self):
        '''清洗数据'''
        self.df['Org_amt'] = self.df.apply(lambda x:x['Org_amt'] if x['Lend_flag']=='11' else x['Org_amt']*(-1), axis=1)
        self.df['Part_acc_no'] = self.df['Part_acc_no'].astype(str) #转字符串
        self.df['Part_acc_no'] = self.df['Part_acc_no'].apply(lambda x:x[-10:]) #截取后10位
        self.df['Part_acc_no'] = self.df['Part_acc_no'].apply(lambda x:re.sub('\D','9',x)) #替换字母为数字
        # 打印数据的前5行
        #print(self.df.head())
        #print(self.df.dtypes)
        
    def extract_df(self, acc_no):
        '''抽取匹配条件的数据'''
        ex_df = self.df[self.df['Acc_no'].eq(acc_no)]
        #print(ex_df)
        return ex_df
        
    def construct_data(self):
        '''构造所需数据'''
        # 构造时间
        self.df['时间'] = self.df.apply(lambda x:x['Date']+' '+x['Time'],axis=1)
        self.df['时间'] = self.df['时间'].apply(lambda x:pd.Timestamp(x))
        #转换数据类型
        #self.df['Date'] = pd.to_datetime(self.df['Date'], format='%Y%m%d')
        #print(self.df['时间'])
        self.df['Part_acc_no'] = self.df['Part_acc_no'].apply(lambda x:pd.to_numeric(x)) #转成整数型
        
    def sort_data(self):
        '''按时间排序'''
        self.df = self.df.sort_values(by='时间', kind='mergesort')
        
    def features1(self):
        '''提取数据特征'''
        df['年']=df['时间'].apply(lambda x: x.year)
        df['月']=df['时间'].apply(lambda x: x.month)
        df['日']=df['时间'].apply(lambda x: x.day)
        df['时']=df['时间'].apply(lambda x: x.hour)
        df['分']=df['时间'].apply(lambda x: x.minute)
        df['秒']=df['时间'].apply(lambda x: x.second)
        # 一天中的第几分钟
        df['一天中的第几分钟']=df['时间'].apply(lambda x: x.minute + x.hour*60)
        # 星期几；
        df['星期几']=df['时间'].apply(lambda x: x.dayofweek)
        # 一年中的第几天
        df['一年中的第几天']=df['时间'].apply(lambda x: x.dayofyear)
        # 一年中的第几周
        df['一年中的第几周']=df['时间'].apply(lambda x: x.week)
        # 一天中哪个时间段：凌晨、早晨、上午、中午、下午、傍晚、晚上、深夜；
        period_dict ={
            23: '深夜', 0: '深夜', 1: '深夜',
            2: '凌晨', 3: '凌晨', 4: '凌晨',
            5: '早晨', 6: '早晨', 7: '早晨',
            8: '上午', 9: '上午', 10: '上午', 11: '上午',
            12: '中午', 13: '中午',
            14: '下午', 15: '下午', 16: '下午', 17: '下午',
            18: '傍晚',
            19: '晚上', 20: '晚上', 21: '晚上', 22: '晚上',
        }
        df['时间段']=df['时'].map(period_dict)

        # 一年中的哪个季度
        season_dict = {
            1: '春季', 2: '春季', 3: '春季',
            4: '夏季', 5: '夏季', 6: '夏季',
            7: '秋季', 8: '秋季', 9: '秋季',
            10: '冬季', 11: '冬季', 12: '冬季',
        }
        df['季节']=df['月'].map(season_dict)
    def features2(self):
        '''提取数据特征'''
        # 是否闰年
        df['是否闰年'] = df['时间'].apply(lambda x: x.is_leap_year)

        # 是否月初
        df['是否月初'] = df['时间'].apply(lambda x: x.is_month_start)

        # 是否月末
        df['是否月末'] = df['时间'].apply(lambda x: x.is_month_end)

        # 是否季节初
        df['是否季节初'] = df['时间'].apply(lambda x: x.is_quarter_start)

        # 是否季节末
        df['是否季节末'] = df['时间'].apply(lambda x: x.is_quarter_end)

        # 是否年初
        df['是否年初'] = df['时间'].apply(lambda x: x.is_year_start)

        # 是否年尾
        df['是否年尾'] = df['时间'].apply(lambda x: x.is_year_end)

        # 是否周末
        df['是否周末'] = df['时间'].apply(lambda x: True if x.dayofweek in [5, 6] else False)

        # 是否公共假期
        public_vacation_list = [
            '20190101', '20190102', '20190204', '20190205', '20190206',
            '20190207', '20190208', '20190209', '20190210', '20190405',
            '20190406', '20190407', '20190501', '20190502', '20190503',
            '20190504', '20190607', '20190608', '20190609', '20190913',
            '20190914', '20190915', '20191001', '20191002', '20191003',
            '20191004', '20191005', '20191006', '20191007',
        ] # 此处未罗列所有公共假期
        df['日期'] = df['时间'].apply(lambda x: x.strftime('%Y%m%d'))
        df['是否公共假期'] = df['日期'].apply(lambda x: True if x in public_vacation_list else False)

        # 是否营业时间
        df['是否营业时间'] = False
        df['小时']=df['时间'].apply(lambda x: x.hour)
        df.loc[((df['小时'] >= 8) & (df['小时'] < 22)), '是否营业时间'] = True

        df.drop(['日期', '小时'], axis=1, inplace=True)
        
    def generate_figure(self, df, title):
        '''绘图'''
        plt.figure(title, figsize=(20,15))
        
        #这里面的gca就是get currant axis
        ax=plt.gca()
        #下面这两句代码就是把右边和上边的轴给弄透明
        ax.spines["right"].set_color("none")
        ax.spines["top"].set_color("none")
        #下面两句代码就是把下边框选作x轴，左边框选作y轴
        #ax.xaxis.set_ticks_position("bottom")
        #ax.yaxis.set_ticks_position("left")
        #将底下的边框移到y=0处，将左边的边框移动到x=0处
        ax.spines["bottom"].set_position(("data",0))
        #ax.spines["left"].set_position(("data",0))
        
        #########################线形图
        plt.plot(df['时间'],df['Balance'],color="black",
                alpha=self.kwargs['FIGURE']['plot_alpha'],
                linewidth=self.kwargs['FIGURE']['plot_width'],
                linestyle="--",label=u"Balance")

        
        #########################散点图  
        # s 点的大小  c 点的颜色 alpha 透明度
        #颜色：b：blue；c：cyan；g：green；k：black；m：magenta；r：red；w：white；y：yellow
        # https://blog.csdn.net/qq_39959348/article/details/108940478
        plt.scatter(df['时间'],df['Org_amt'], 
                s=self.kwargs['FIGURE']['scatter_shape'],
                c=df['Part_acc_no'],
                cmap='gist_rainbow',
                alpha=self.kwargs['FIGURE']['scatter_alpha'], 
                label=u"Org_amt")


        ##############################设置坐标轴
        #标题
        plt.title(title)
        #添加文本 #x轴文本
        #plt.xlabel('Date')
        #y轴文本
        #plt.ylabel('Org_amt')
        #添加图例
        plt.legend(loc="best")
        if self.kwargs['FIGURE']['save']=='Y':
            plt.savefig(os.path.join(self.kwargs['FIGURE']['folder'],title+'.png'), dpi=300, papertype='a3')
            print('【保存图片】',title+'.png')
        else:
            #plt.get_current_fig_manager().full_screen_toggle() #全屏
            plt.get_current_fig_manager().window.state('zoomed') #窗口最大化
            plt.show()